/**
 * This class embodies the hosts and their appropriate states.
 */
package org.hackystat.ui.telemetryviewer.client;

import java.util.Date;

import org.hackystat.ui.telemetryviewer.client.common.BasicConveyor;
import org.hackystat.ui.telemetryviewer.client.common.PropertyKeys;
import org.hackystat.ui.telemetryviewer.client.common.Session;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.WindowResizeListener;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * This class embodies the hosts and their appropriate states.
 * @author David J. Nickles
 *
 */
public class HostStatusPanel implements WindowResizeListener {

  private Boolean sensorbaseStatus;
  //private Boolean dpdStatus;
  private Boolean telemetryStatus;
  private Date sensorbaseTstamp;
  //private Date dpdTstamp;
  private Date telemetryTstamp;
  private Label sensorbaseHost;
  private Label sensorbaseFeedback;
  //private Label dpdHost;
  //private Label dpdFeedback;
  private Label telemetryHost;
  private Label telemetryFeedback;
  //private HorizontalPanel mainPanel;
  private Grid grid;
  private Image sensorbaseHostImage;
  //private Image dpdHostImage;
  private Image telemetryHostImage;
  private Session session;
  private UserSettingsPanel userPanel;
  
  /**
   * Construct a valid set of hosts.
   * 
   * @param session the current session attributes
   */
  public HostStatusPanel(Session session) {
    
    grid = new Grid(1,4);
    this.session = session;
    grid.setStyleName(Styles.BASICPANEL);
    //mainPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
    
    VerticalPanel column1 = new VerticalPanel();
    column1.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
    column1.setStyleName(Styles.SIMPLEPANEL);
    this.sensorbaseHostImage = new Image(Images.HOST_IMAGE);
    column1.add(this.sensorbaseHostImage);
    Label sensorbaseImageLabel = new Label("Sensorbase");
    sensorbaseImageLabel.setStyleName(Styles.SMALLLABEL);
    column1.add(sensorbaseImageLabel); 
    grid.setWidget(0, 0, column1);
    
    /*
    VerticalPanel column2 = new VerticalPanel();
    column2.setHorizontalAlignment(ALIGN_CENTER);
    column2.setStyleName(Styles.HOSTPANELSTYLE);
    this.dpdHostImage = new Image(Images.HOST_IMAGE);
    column2.add(this.dpdHostImage);
    Label dpdImageLabel = new Label("DailyProjectData");
    dpdImageLabel.setStyleName(Styles.SMALLLABELSTYLE);
    column2.add(dpdImageLabel); 
    add(column2);
    */
    
    VerticalPanel column3 = new VerticalPanel();
    column3.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
    column3.setStyleName(Styles.SIMPLEPANEL);
    this.telemetryHostImage = new Image(Images.HOST_IMAGE);
    column3.add(this.telemetryHostImage);
    Label telemetryImageLabel = new Label("Telemetry");
    telemetryImageLabel.setStyleName(Styles.SMALLLABEL);
    column3.add(telemetryImageLabel); 
    grid.setWidget(0, 1, column3);
    
    VerticalPanel column4 = new VerticalPanel();
    column4.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
    
    HorizontalPanel col4row1 = new HorizontalPanel();
    Label sbPrefixLabel = new Label("Sensorbase URI:");
    sbPrefixLabel.setStyleName(Styles.URILABEL);
    col4row1.add(sbPrefixLabel);
    this.sensorbaseHost = new Label("default-uri");
    this.sensorbaseHost.setStyleName(Styles.URILABEL);
    col4row1.add(this.sensorbaseHost);
    column4.add(col4row1);
    this.sensorbaseFeedback = new Label("Sensorbase Feedback.");
    this.sensorbaseFeedback.setStyleName(Styles.EXAMPLELABEL);
    column4.add(this.sensorbaseFeedback);
    
    /*
    HorizontalPanel col4row2 = new HorizontalPanel();
    Label dpdPrefixLabel = new Label("DailyProjectData URI:");
    dpdPrefixLabel.setStyleName(Styles.URILABEL);
    col4row2.add(dpdPrefixLabel);
    this.dpdHost = new Label("default-uri");
    this.dpdHost.setStyleName(Styles.URILABEL);
    col4row2.add(this.dpdHost);
    column4.add(col4row2);
    this.dpdFeedback = new Label("DailyProjectData Feedback.");
    this.dpdFeedback.setStyleName(Styles.EXAMPLELABELSTYLE);
    column4.add(this.dpdFeedback);
    */
    
    HorizontalPanel col4row3 = new HorizontalPanel();
    Label telPrefixLabel = new Label("Telemetry URI:");
    telPrefixLabel.setStyleName(Styles.URILABEL);
    col4row3.add(telPrefixLabel);
    this.telemetryHost = new Label("default-uri");
    this.telemetryHost.setStyleName(Styles.URILABEL);
    col4row3.add(this.telemetryHost);
    column4.add(col4row3);
    this.telemetryFeedback = new Label("Telemetry Feedback.");
    this.telemetryFeedback.setStyleName(Styles.EXAMPLELABEL);
    column4.add(this.telemetryFeedback);
    
    grid.setWidget(0, 2, column4);
    grid.setWidget(0, 3, new HTML(CompositeWidget.OPEN_ELEMENT + CompositeWidget.USER_ELEMENT_ID
      + CompositeWidget.CLOSE_ELEMENT));
    
    Window.addWindowResizeListener(this);
    grid.setWidth(Integer.toString(Window.getClientWidth() - 42) + Styles.PIXELSUFFIX);
    RootPanel.get(CompositeWidget.HOST_ELEMENT_ID).add(grid);
  }
  
  /**
   * This method initializes this object by performing a series of RPC calls.
   */
  public final void init() {
    rpcGetHosts();
  }
  
  /**
   * This method sets the name of the host uri.
   * @param conveyor carrying the host service URIs.
   */
  private final void setHosts(BasicConveyor conveyor) {
    if (Boolean.TRUE.toString().equals(conveyor.getStatus())) {
      
      String sensorbaseHostUri = (String)conveyor.getMap().get(PropertyKeys.SENSORBASE_HOST);
      if (sensorbaseHostUri == null) {
        this.sensorbaseHost.setText("");
        this.session.setSensorbaseHost("");
        this.sensorbaseHostImage.setUrl(Images.HOST_INVALID);
        this.sensorbaseFeedback.setText("Property file does not contain sensorbase host value.");
      }
      else {
        this.sensorbaseHost.setText(sensorbaseHostUri);
        this.session.setSensorbaseHost(sensorbaseHostUri);
        this.sensorbaseHostImage.setUrl(Images.HOST_IMAGE);
        this.sensorbaseFeedback.setText("Sensorbase host property value located.");
      }
      /*
      String dpdHostUri = (String)conveyor.getMap().get(PropertyKeys.DPD);
      if (dpdHostUri == null) {
        this.dpdHost.setText("");
        this.session.setTelemetryHost("");
        this.dpdHostImage.setUrl(Images.HOST_INVALID);
        this.dpdFeedback.setText("Property file does not contain DailyProjectData host value.");
      }
      else {
        this.dpdHost.setText(dpdHostUri);
        this.session.setTelemetryHost(dpdHostUri);
        this.dpdHostImage.setUrl(Images.HOST_IMAGE);
        this.dpdFeedback.setText("DailyProjectData host property value located.");
      }
      */
      String telemetryHostUri = (String)conveyor.getMap().get(PropertyKeys.TELEMETRY_HOST);
      if (telemetryHostUri == null) {
        this.telemetryHost.setText("");
        this.session.setTelemetryHost("");
        this.telemetryHostImage.setUrl(Images.HOST_INVALID);
        this.telemetryFeedback.setText("Property file does not contain telemetry host value.");
      }
      else {
        this.telemetryHost.setText(telemetryHostUri);
        this.session.setTelemetryHost(telemetryHostUri);
        this.telemetryHostImage.setUrl(Images.HOST_IMAGE);
        this.telemetryFeedback.setText("Telemetry host property value located.");
      }
      rpcIsSensorbaseHost();
    }
    else {
      CompositeWidget.showAlert(conveyor.getStatus());
    }
  }
  
  /**
   * Check with the servlet to get the host name from the properties file.
   */
  private final void rpcGetHosts() {
    this.sensorbaseHostImage.setUrl(Images.WAIT_IMAGE);
    this.sensorbaseHostImage.setSize(Styles.BGIMAGESIZE, Styles.BGIMAGESIZE);
    //this.dpdHostImage.setUrl(Images.WAIT_IMAGE);
    //this.dpdHostImage.setSize(Styles.IMAGESIZE, Styles.IMAGESIZE);
    this.telemetryHostImage.setUrl(Images.WAIT_IMAGE);
    this.telemetryHostImage.setSize(Styles.BGIMAGESIZE, Styles.BGIMAGESIZE);
    this.telemetryFeedback.setText("Searching for the telemetry properties file.");
    RPCServiceFactory.getInstance().getService().getHosts(new AsyncCallback()
    {
      public void onSuccess(Object result) {
        setHosts((BasicConveyor) result);
      }
  
      public void onFailure(Throwable caught) {
        if (caught instanceof com.google.gwt.user.client.rpc.InvocationException) {
          CompositeWidget.log(RPCServiceFactory.PRCERRORNAME, 
            "Cannot invoke get-properties on servlet.");
        } 
        else {
          CompositeWidget.log(RPCServiceFactory.PRCERRORNAME, caught.toString());
        }
      }
    });
  }
  
  /**
   * This method sets the state of the sensorbase service in the UI.
   * @param state Boolean represents the state of the user valid=true, invalid=false
   */
  public void setSensorbaseHostStatus(Boolean state) {
    this.sensorbaseHostImage.setUrl(Images.HOST_IMAGE);
    this.sensorbaseTstamp = new Date();
    String time = DateTimeFactories.getInstance().getBodyfactory().format(this.sensorbaseTstamp);
    if (state != null && state.booleanValue()) {
      this.sensorbaseStatus = Boolean.TRUE;
      this.sensorbaseHostImage.setUrl(Images.HOST_VALID);
      this.sensorbaseFeedback.setText(time + ", Sensorbase service contacted successfully.");
      this.sensorbaseFeedback.setStyleName(Styles.VALIDLABEL);
      (userPanel = new UserSettingsPanel(this.session)).init();
    } 
    else {
      this.sensorbaseStatus = Boolean.FALSE;
      this.sensorbaseHostImage.setUrl(Images.HOST_INVALID);
      this.sensorbaseFeedback.setText(time + ", Sensorbase service unavailable.");
      this.sensorbaseFeedback.setStyleName(Styles.INVALIDLABEL);
    }
    rpcIsTelemetryHost();
  }
  
  /**
   * This method performs an RPC call to the servlet to check if the sensorbase service is up.
   */
  private void rpcIsSensorbaseHost() {
    this.sensorbaseHostImage.setUrl(Images.WAIT_IMAGE);
    this.sensorbaseHostImage.setSize(Styles.BGIMAGESIZE, Styles.BGIMAGESIZE);
    RPCServiceFactory.getInstance().getService().isSensorBaseHost(this.sensorbaseHost.getText(),
      new AsyncCallback()
      {
        public void onSuccess(Object result) {
          setSensorbaseHostStatus((Boolean) result);
        }
    
        public void onFailure(Throwable caught) {
          if (caught instanceof com.google.gwt.user.client.rpc.InvocationException) {
            CompositeWidget.log(RPCServiceFactory.PRCERRORNAME, 
              "Cannot invoke host validation on servlet.");
          } 
          else {
            CompositeWidget.log(RPCServiceFactory.PRCERRORNAME, caught.toString());
          }
        }
      });
  }
  
  /**
   * This method sets the state of the telemetry service in the UI.
   * @param state Boolean represents the state of the user valid=true, invalid=false
   */
  public void setTelemetryHostStatus(Boolean state) {
    this.telemetryHostImage.setUrl(Images.HOST_IMAGE);
    this.telemetryTstamp = new Date();
    String time = DateTimeFactories.getInstance().getBodyfactory().format(this.telemetryTstamp);
    if (state != null && state.booleanValue()) {
      this.telemetryStatus = Boolean.TRUE;
      this.telemetryHostImage.setUrl(Images.HOST_VALID);
      this.telemetryFeedback.setText(time + ", Telemetry service contacted successfully.");
      this.telemetryFeedback.setStyleName(Styles.VALIDLABEL);
    } 
    else {
      this.telemetryStatus = Boolean.FALSE;
      this.telemetryHostImage.setUrl(Images.HOST_INVALID);
      this.telemetryFeedback.setText(time + ", Telemetry service unavailable.");
      this.telemetryFeedback.setStyleName(Styles.INVALIDLABEL);
    }
  }
  
  /**
   * This method performs an RPC call to the servlet to check if the telemetry service is up.
   */
  private void rpcIsTelemetryHost() {
    this.telemetryHostImage.setUrl(Images.WAIT_IMAGE);
    this.telemetryHostImage.setSize(Styles.BGIMAGESIZE, Styles.BGIMAGESIZE);
    RPCServiceFactory.getInstance().getService().isTelemetryHost(this.telemetryHost.getText(),
      new AsyncCallback()
      {
        public void onSuccess(Object result) {
          setTelemetryHostStatus((Boolean) result);
        }
    
        public void onFailure(Throwable caught) {
          if (caught instanceof com.google.gwt.user.client.rpc.InvocationException) {
            CompositeWidget.log(RPCServiceFactory.PRCERRORNAME, 
              "Cannot invoke host validation on servlet.");
          } 
          else {
            CompositeWidget.log(RPCServiceFactory.PRCERRORNAME, caught.toString());
          }
        }
      });
  }
  
  /**
   * This method returns if the sensorbase service is available.
   * @return true if the sensorbase service has been contacted successfully, false if not.
   */
  public Boolean getSensorbaseStatus() {
    return this.sensorbaseStatus;
  }
  
  /**
   * This method returns if the telemetry service is available.
   * @return true if the telemetry service has been contacted successfully, false if not.
   */
  public Boolean getTelemetryStatus() {
    return this.telemetryStatus;
  }
  
  /** 
   * Listens for user resizing of the window.
   * @param width of the adjusted window..
   * @param height of the adjusted window.
   */
  public void onWindowResized(int width, int height) {
    grid.setWidth(Integer.toString(width - Styles.RIGHTOFFSET) + Styles.PIXELSUFFIX);
  }
}
